package com.cloud.utils;

import com.cloud.enums.TableOps;
import com.cloud.model.entity.ASTNode;
import com.cloud.model.entity.ConditionNode;
import com.cloud.model.entity.OperatorNode;
import com.cloud.model.req.ComplexFilter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class RuleUtils {

    public static String getReplaceExpressionByMap(String expression, Map<String,String> variables){
        // 定义正则表达式以匹配单引号中的内容
        String regex = "'([^']*)'";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(expression);
        // 替换计数器
        int valueCounter = 1;
        // StringBuffer 用于保存构造的新字符串
        StringBuffer result = new StringBuffer();
        // tempMap 存储替换值
        Map<String, String> tempMap = new HashMap<>();
        while (matcher.find()) {
            // 获取匹配到的内容
            String matchedValue = matcher.group(1);
            String variableName = "value"+valueCounter;
            // 生成替换文本
            String replacement = "tempMap['" + variableName+"']";
            // 存入 tempMap
            tempMap.put(variableName, matchedValue);
            // 用生成的替换文本替换原字符串
            matcher.appendReplacement(result, replacement);
            valueCounter++;
        }
        // 将最后的部分添加到结果中
        matcher.appendTail(result);
        tempMap.forEach((key, value) -> System.out.println(key + " : " + value));
        variables.putAll(tempMap);
        return result.toString();
    }

    public static String getReplaceExpressionByString(String expression, Map<String,String> variables){
        // 定义正则表达式以匹配单引号中的内容
        String regex = "'([^']*)'";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(expression);
        // 替换计数器
        int valueCounter = 1;
        // StringBuffer 用于保存构造的新字符串
        StringBuilder result = new StringBuilder();
        // tempMap 存储替换值
        Map<String, String> tempMap = new HashMap<>();
        while (matcher.find()) {
            // 获取匹配到的内容
            String matchedValue = matcher.group(1);
            String variableName = "value"+valueCounter;
            // 存入 tempMap
            tempMap.put(variableName, matchedValue);
            // 用生成的替换文本替换原字符串
            matcher.appendReplacement(result, variableName);
            valueCounter++;
        }
        // 将最后的部分添加到结果中
        matcher.appendTail(result);
        variables.putAll(tempMap);
        return result.toString();
    }

    private static TableOps convertOperator(String operator) {
        switch (operator) {
            case "==":
                return TableOps.EQUALS; // 假设 TableOps 枚举里有 EQUALS 对应 ==
            case "!=":
                return TableOps.NOT_EQUALS; // 假设 TableOps 枚举里有 NOT_EQUALS
            // 可扩展更多操作符
            default:
                throw new IllegalArgumentException("Unsupported operator: " + operator);
        }
    }
    public static ComplexFilter convertToComplexFilter(ASTNode node) {
        if (node instanceof OperatorNode) {
            // 如果是逻辑操作节点（AND/OR）
            OperatorNode opNode = (OperatorNode) node;

            // 创建一个逻辑节点的 ComplexFilter
            ComplexFilter filter = new ComplexFilter();
            filter.setJoiner(opNode.getOperator().toUpperCase()); // 设置连接方式 AND/OR

            // 递归处理左子树和右子树
            List<ComplexFilter> subFilters = new ArrayList<>();
            subFilters.add(convertToComplexFilter(opNode.getLeft()));
            subFilters.add(convertToComplexFilter(opNode.getRight()));

            filter.setFilters(subFilters); // 设置子节点
            return filter;

        } else if (node instanceof ConditionNode) {
            // 如果是条件节点
            ConditionNode condNode = (ConditionNode) node;

            // 创建叶子节点的 ComplexFilter
            ComplexFilter filter = new ComplexFilter();
            filter.setProperties(condNode.getField()); // 属性名
            filter.setOps(convertOperator(condNode.getOperator())); // 操作符转换
            filter.setFilterValue(condNode.getValue().replace("'", "")); // 移除引号后设置值
            return filter;

        } else {
            throw new RuntimeException("Unknown AST node type: " + node.getClass().getName());
        }
    }

    public static void printComplexFilter(ComplexFilter filter, int indent) {
        for (int i = 0; i < indent; i++) {
            System.out.print("  ");
        }
        if (filter.getJoiner() != null) {
            // 打印逻辑节点
            System.out.println("JOINER: " + filter.getJoiner());
            List<ComplexFilter> subFilters = filter.getFilters();
            if (subFilters != null) {
                for (ComplexFilter subFilter : subFilters) {
                    printComplexFilter(subFilter, indent + 1);
                }
            }
        } else {
            // 打印叶子节点
            System.out.println("CONDITION: " +
                    filter.getProperties() + " " +
                    filter.getOps() + " " +
                    filter.getFilterValue());
        }
    }

    // 主方法：将 ComplexFilter 转换为 SQL 字符串
    public static String buildSql(ComplexFilter filter) {
        if (filter == null) {
            return "";
        }

        // 如果这是一个逻辑节点 (joiner != null)
        if (filter.getJoiner() != null) {
            String joiner = filter.getJoiner().toUpperCase(); // 确保是 "AND" 或 "OR"
            List<ComplexFilter> subFilters = filter.getFilters();

            if (subFilters == null || subFilters.isEmpty()) {
                return ""; // 如果没有子节点，返回空
            }

            // 递归生成子条件 SQL
            String subSql = subFilters.stream()
                    .map(RuleUtils::buildSql) // 递归处理每个子节点
                    .filter(sql -> !sql.isEmpty()) // 过滤掉空的子节点
                    .collect(Collectors.joining(" " + joiner + " ")); // 用 joiner 连接 SQL 条件

            return "(" + subSql + ")"; // 用括号包裹逻辑条件
        }

        // 如果是叶子节点（没有 joiner，包含 properties, ops 等）
        if (filter.getProperties() != null && filter.getOps() != null) {
            String property = filter.getProperties(); // 字段名
            TableOps ops = filter.getOps(); // 操作符
            Object value = filter.getFilterValue(); // 值

            return buildConditionSql(property, ops, value);
        }

        return ""; // 空节点返回空字符串
    }

    // 构建单一条件的 SQL
    private static String buildConditionSql(String property, TableOps ops, Object value) {
        switch (ops) {
            case EQUALS: // "字段 = 值"
                return property + " = " + formatValue(value);
            case NOT_EQUALS: // "字段 != 值"
                return property + " != " + formatValue(value);
            case IN: // "字段 IN (值1, 值2, ...)"
                if (value instanceof List) {
                    List<?> values = (List<?>) value;
                    return property + " IN (" +
                            values.stream()
                                    .map(RuleUtils::formatValue)
                                    .collect(Collectors.joining(", ")) +
                            ")";
                } else {
                    throw new IllegalArgumentException("IN 操作符需要提供一个值列表");
                }
            case IS_NULL: // "字段 IS NULL"
                return property + " IS NULL";
            case IS_NOT_NULL: // "字段 IS NOT NULL"
                return property + " IS NOT NULL";
            default:
                throw new UnsupportedOperationException("不支持的操作符: " + ops);
        }
    }

    // 格式化值为 SQL 字符串（考虑字符串、数字等类型）
    private static String formatValue(Object value) {
        if (value == null) {
            return "NULL";
        } else if (value instanceof String) {
            return "'" + value.toString().replace("'", "''") + "'"; // 转义单引号
        }
        return value.toString(); // 其他类型直接转换为字符串
    }

    public static void printAST(ASTNode node, int indent) {
        for (int i = 0; i < indent; i++) {
            System.out.print("  ");
        }
        if (node instanceof OperatorNode) {
            OperatorNode opNode = (OperatorNode) node;
            System.out.println(opNode.getOperator());
            printAST(opNode.getLeft(), indent + 1);
            printAST(opNode.getRight(), indent + 1);
        } else if (node instanceof ConditionNode) {
            ConditionNode condNode = (ConditionNode) node;
            System.out.println(condNode.getField() + " " + condNode.getOperator() + " " + condNode.getValue());
        }
    }

}
